package com.nenglai.admin.handler;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.JWTVerifier;
import com.nenglai.admin.modular.system.service.ReportAdminService;
import com.nenglai.common.jwt.VerifyToken;
import com.nenglai.common.response.ErrorCode;
import com.nenglai.common.response.ResponseException;
import com.nenglai.model.system.entity.Admin;
import lombok.AllArgsConstructor;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

@AllArgsConstructor
public class AuthenticationInterceptor implements HandlerInterceptor {

    private final ReportAdminService adminService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {

        response.setHeader("Access-Control-Allow-Origin", "*");
//        response.setHeader("Access-Control-Allow-Credentials", "true");//
        response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS");
        response.setHeader("Access-Control-Max-Age", "86400");
        response.setHeader("Access-Control-Allow-Headers", "token");
        // 如果是OPTIONS请求则结束
        if (HttpMethod.OPTIONS.toString().equals(request.getMethod())) {
            response.setStatus(HttpStatus.NO_CONTENT.value());
            return false;
        }

        // 如果不是映射到方法直接通过
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }

        // TODO 无VerifyToken注释或required为false的无需认证
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        // 检查是否有 VerifyToken 注释，没有则跳过认证
        if (method.isAnnotationPresent(VerifyToken.class)) {

            VerifyToken verifyToken = method.getAnnotation(VerifyToken.class);
            if (verifyToken.required()) {

                String token = request.getHeader("token"); // 从 http 请求头中取出 token

                // 执行认证
                if (token == null) {
                    throw new ResponseException(ErrorCode.TOKEN_NOT_FOUND);
                }

                Long userId;
                try {
                    String user = JWT.decode(token).getClaim("user").asString();
                    userId = Long.parseLong(user);
                } catch (JWTDecodeException j) {
                    throw new ResponseException(ErrorCode.AUTH_ERROR);
                }

                Admin admin = adminService.findOne(userId);
                if (admin == null) {
                    throw new ResponseException(ErrorCode.AUTH_ERROR);
                }

                // 验证 token
                JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(admin.getPassword())).build();
                try {
                    jwtVerifier.verify(token);
                } catch (JWTVerificationException e) {
                    throw new ResponseException(ErrorCode.AUTH_ERROR);
                }

                request.setAttribute("user", admin);

            }

        }

        return true;
    }
}